package system;

import gui.DrawingPanel;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

/**
 * @author Kevin Peters
 */
public final class ImageFactory {
	public final static String resourcePath = SystemProperties.RESOURCEPATH;
	private static BufferedImage image = null;

	/**
	 * Load the image from the given path
	 * 
	 * @param imagePath
	 * @return A BufferedImage loaded from the given path
	 * @throws NullPointerException
	 */
	public static BufferedImage loadImage(String imagePath, boolean extern)
			throws NullPointerException {
		URL url = null;
		if (!extern) {
			url = ImageFactory.class.getClassLoader().getResource(imagePath);
		} else {
			try {
				url = new URL(SystemProperties.FILE_PROTOCOL_PREFIX + imagePath);

			} catch (MalformedURLException e1) {
				e1.printStackTrace();
			}
		}

		if (url != null) {
			try {
				URLConnection urlConnection = url.openConnection();
				InputStream input = urlConnection.getInputStream();
				image = ImageIO.read(input);
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return image;

		} else {
			return null;
		}
	}

	/**
	 * Splits the given image into tile, defined by the given cols and rows
	 * 
	 * @param sourceImage
	 * @param cols
	 * @param rows
	 * @return Map<Integer,ImagePart> with the ImagePart and its id
	 */
	public static Map<Integer, ImagePart> splitImage(BufferedImage sourceImage,
			int cols, int rows) {

		Map<Integer, ImagePart> imagePartMap = new HashMap<Integer, ImagePart>();
		int imageWidth = sourceImage.getWidth() / cols;
		int imageHeight = sourceImage.getHeight() / rows;
		int index = 0;
		for (int row = 0; row < rows; row++) {
			for (int col = 0; col < cols; col++) {
				if (SystemProperties.FILLEDSOURCEPANELS.contains(index)) {
					BufferedImage imageTile = new BufferedImage(imageWidth,
							imageHeight, BufferedImage.TYPE_INT_RGB);
					ImagePart imagePart = new ImagePart();
					imagePart.setImage(imageTile);
					imagePart.setSourceCoordinateX(col);
					imagePart.setSourceCoordinateY(row);
					imagePart.setSourceIndex(index);
					imagePart
							.setEditorIndex(SystemProperties.PANELMAPPING_SOURCE2EDITOR
									.get(index));
					imagePartMap.put(index, imagePart);
					Graphics2D imageTileGraphics = imageTile.createGraphics();
					imageTileGraphics.drawImage(sourceImage, 0, 0, imageWidth,
							imageHeight, imageWidth * col, imageHeight * row,
							imageWidth * col + imageWidth, imageHeight * row
									+ imageHeight, null);
					imageTileGraphics.dispose();
				}
				index++;
			}
		}
		return imagePartMap;
	}

	/**
	 * Saves the current image to destinated file
	 * 
	 * @param savePath
	 * @param drawingPanelMap
	 */
	public static void saveImage(String savePath,
			Map<Integer, DrawingPanel> drawingPanelMap) {
		BufferedImage newImage = new BufferedImage(
				SystemProperties.NEW_IMAGE_WIDTH,
				SystemProperties.NEW_IMAGE_HEIGTH, BufferedImage.TYPE_INT_RGB);
		Graphics2D graphics = newImage.createGraphics();

		int index = 0;
		for (int row = 0; row < SystemProperties.RESOURCEROWS; row++) {
			for (int col = 0; col < SystemProperties.RESOURCECOLS; col++) {
				if (SystemProperties.FILLEDSOURCEPANELS.contains(index)) {

					int dx1 = SystemProperties.GRIDPANELSIDELENGTH * col;
					int dy1 = SystemProperties.GRIDPANELSIDELENGTH * row;
					int dx2 = SystemProperties.GRIDPANELSIDELENGTH * col
							+ SystemProperties.GRIDPANELSIDELENGTH;
					int dy2 = SystemProperties.GRIDPANELSIDELENGTH * row
							+ SystemProperties.GRIDPANELSIDELENGTH;
					int sx1 = 0;
					int sy1 = 0;
					int sx2 = SystemProperties.GRIDPANELSIDELENGTH;
					int sy2 = SystemProperties.GRIDPANELSIDELENGTH;

					graphics.drawImage(drawingPanelMap.get(index)
							.getImagePart().getImage(), dx1, dy1, dx2, dy2,
							sx1, sy1, sx2, sy2, null);
				}
				index++;
			}
		}

		String fileExtension = "." + SystemProperties.FILE_EXTENSION;

		if (!savePath.endsWith(fileExtension)) {
			savePath += fileExtension;
		}
		File outputfile = new File(savePath);
		try {
			ImageIO.write(newImage, SystemProperties.FILE_EXTENSION, outputfile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
